package com.bzframework.project.api.web;

import com.bzframework.pro.api.core.manager.ApiSupportManager;
import com.bzframework.pro.api.core.provider.ApiSupport;
import com.bzframework.pro.api.core.provider.CompositeApiSupport;
import com.bzframework.pro.authorize.adapter.ReactiveServiceCrudControllerAdapter;
import com.bzframework.pro.authorize.annotation.Authorization;
import com.bzframework.project.api.entity.OpenApiEntity;
import com.bzframework.project.api.model.request.ApiInvokeRequest;
import com.bzframework.project.api.service.OpenApiService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.RequiredArgsConstructor;
import lombok.SneakyThrows;
import org.hswebframework.web.api.crud.entity.PagerResult;
import org.hswebframework.web.api.crud.entity.QueryParamEntity;
import org.hswebframework.web.bean.FastBeanCopier;
import org.hswebframework.web.crud.service.ReactiveCrudService;
import org.springframework.http.HttpHeaders;
import org.springframework.http.codec.multipart.FilePart;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

/**
 * @Author bingzhong
 * @Date 2025/3/3 14:20
 * @Description
 */
@Tag(name = "openapi", description = "openapi")
@RestController
@RequestMapping("/openapi")
@RequiredArgsConstructor
public class OpenApiController implements ReactiveServiceCrudControllerAdapter<OpenApiEntity, String> {

    private final ApiSupportManager apiSupportManager;

    private final OpenApiService openApiService;
    @Override
    public ReactiveCrudService<OpenApiEntity, String> getService() {
        return openApiService;
    }

    @GetMapping("/supports")
    @Operation(summary = "只返回jar中得解析的api")
    @Authorization(ignore = true)
    public Flux<ApiSupport> getApiSupports() {
        return Flux.fromIterable(
                apiSupportManager.getApiSupportsMap()
                                 .values()
                                 .stream()
                                 .flatMap(list -> Arrays.stream(list.toArray(new ApiSupport[0])))
                                 .collect(Collectors.toList())
        );
    }

    @PostMapping("/upload")
    @Authorization(ignore = true)
    @Operation(summary = "上传 ApiSupport jar包")
    public Mono<String> uploadApiSupportJar(@RequestPart("file")FilePart filePart) {
        return openApiService.uploadApiSupportJar(filePart);
    }

    @Override
    @Authorization(ignore = true)
    public Flux<OpenApiEntity> query(Mono<QueryParamEntity> query) {
        return ReactiveServiceCrudControllerAdapter.super.query(query);
    }

    @PostMapping("/invoke")
    @Operation(summary = "Api接口调用")
    @Authorization(ignore = true)
    public Mono<String> apiInvoke(@RequestBody @Validated ApiInvokeRequest apiInvokeRequest) {
        return openApiService.apiInvoke(apiInvokeRequest);
    }

    @GetMapping("/get")
    @Operation(summary = "Api接口调用")
    @Authorization(ignore = true)
    @SneakyThrows
    public Mono<String> testGet(String name) {
        System.out.println("name = " + name);
        TimeUnit.SECONDS.sleep(15);
        return Mono.justOrEmpty(name);
    }

    @PostMapping("/post")
    @Operation(summary = "Api接口调用")
    @Authorization(ignore = true)
    public Mono<String> testPost(ServerWebExchange webExchange) {
        HttpHeaders headers = webExchange.getRequest().getHeaders();
        return Mono.justOrEmpty(headers.toString());
    }

    @GetMapping("/details")
    @Authorization(ignore = true)
    @Operation(summary = "分页查询Api列表")
    public Mono<PagerResult<ApiSupport>> queryOpenApis(@RequestParam String name,
                                                       @RequestParam(defaultValue = "0") Integer pageIndex,
                                                       @RequestParam(defaultValue = "12") Integer pageSize) {
        return openApiService.createQuery()
                             .fetch()
                             .map(openApiEntity -> FastBeanCopier.copy(openApiEntity, CompositeApiSupport.class))
                             .collectList()
                             .map(apiSupports -> {
                                 List<ApiSupport> supports = new ArrayList<>();
                                 supports.addAll(
                                         apiSupportManager.getApiSupportsMap().values()
                                                          .stream()
                                                          .flatMap(list -> Arrays.stream(list.toArray(new ApiSupport[0])))
                                                          .collect(Collectors.toList())
                                 );
                                 supports.addAll(apiSupports);
                                 supports = supports.stream()
                                                    .filter(entity -> entity.getName().contains(name))
                                                    .collect(Collectors.toList());
                                 return PagerResult.of(supports.size(),
                                                       supports.subList(pageIndex, Math.min(pageSize, supports.size())));
                             });

    }

    @GetMapping("/detail/{id}")
    @Operation(summary = "根据id获取Api")
    public Mono<ApiSupport> getOpenApiById(@PathVariable String id) {

        return Flux.fromIterable(apiSupportManager.getApiSupportsMap().values())
                   .flatMap(Flux::fromIterable)
                   .filter(apiSupport -> apiSupport.getId().equals(id))
                   .next()
                   .switchIfEmpty(openApiService.findById(id)
                                                .map(e -> FastBeanCopier.copy(e, new CompositeApiSupport())));


    }

}
